home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / mawk10.zip / EXECUTE.C < prev    next >
C/C++ Source or Header  |  1991-10-05  |  30KB  |  1,063 lines

  1.  
  2. /********************************************
  3. execute.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the AWK programming language.
  8.  
  9. Mawk is distributed without warranty under the terms of
  10. the GNU General Public License, version 2, 1991.
  11. ********************************************/
  12.  
  13. /* $Log:    execute.c,v $
  14.  * Revision 3.6.1.1  91/09/14  17:23:03  brennan
  15.  * VERSION 1.0
  16.  * 
  17.  * Revision 3.6  91/08/16  11:01:26  brennan
  18.  * Carl's addition of SW_FP_CHECK for V7 XNX23A
  19.  * 
  20.  * Revision 3.5  91/08/13  06:51:08  brennan
  21.  * VERSION .9994
  22.  * 
  23.  * Revision 3.4  91/06/28  04:16:28  brennan
  24.  * VERSION 0.999
  25.  * 
  26.  * Revision 3.3  91/06/19  10:23:28  brennan
  27.  * changes for xenix_r2, call this version 0.997
  28.  * 
  29.  * Revision 3.2  91/06/15  09:12:22  brennan
  30.  * Carl's diffs for V7
  31.  * 
  32.  * 06/12/91  C. Mascott        use D2BOOL macro for logical
  33.  *                  test on double
  34.  *
  35.  * Revision 3.1  91/06/07  10:27:14  brennan
  36.  * VERSION 0.995
  37.  * 
  38.  * Revision 2.5  91/05/23  15:45:44  brennan
  39.  * fixed bug in _TEST:  case C_STRNUM
  40.  * 
  41.  * Revision 2.4  91/05/22  07:43:29  brennan
  42.  * small change to work around bug in TurboC++
  43.  * 
  44.  * Revision 2.3  91/05/15  12:07:31  brennan
  45.  * dval hash table for arrays
  46.  * 
  47.  * Revision 2.2  91/04/09  12:38:54  brennan
  48.  * added static to funct decls to satisfy STARDENT compiler
  49.  * 
  50.  * Revision 2.1  91/04/08  08:22:55  brennan
  51.  * VERSION 0.97
  52.  * 
  53. */
  54.  
  55.  
  56. #include "mawk.h"
  57. #include "code.h"
  58. #include "memory.h"
  59. #include "symtype.h"
  60. #include "field.h"
  61. #include "bi_funct.h"
  62. #include "regexp.h"
  63. #include "repl.h"
  64. #include <math.h>
  65.  
  66. /* static functions */
  67. static int PROTO( compare, (CELL *) ) ;
  68. static void PROTO( eval_overflow, (void) ) ;
  69.  
  70.  
  71. #if   NOINFO_SIGFPE
  72. static char dz_msg[] = "division by zero" ;
  73. #endif
  74.  
  75. #ifdef   DEBUG
  76. #define  inc_sp()   if( ++sp == eval_stack+EVAL_STACK_SIZE )\
  77.                          eval_overflow()
  78. #else
  79.  
  80. /* If things are working, the only reason the eval stack should
  81.    overflow is too much function recursion
  82.    (checked for at _CALL below  */
  83.  
  84. #define inc_sp()    sp++
  85. #endif
  86.  
  87. #define  SAFETY    3    /* if we get within 3 of stack top emit 
  88.          overflow */
  89.  
  90. /*  The stack machine that executes the code */
  91.  
  92. CELL  eval_stack[EVAL_STACK_SIZE] ;
  93.  
  94. static void eval_overflow()
  95. { overflow("eval stack" , EVAL_STACK_SIZE) ; mawk_exit(1) ; }
  96.  
  97. /* if this flag is on, recursive calls to execute need to
  98.    return to the _CALL statement.  This only happens
  99.    inside array loops */
  100. int  returning ;  
  101.  
  102. INST  *execute(cdp, sp, fp)
  103.   register INST *cdp ;  /* code ptr, start execution here */
  104.   register CELL *sp ;   /* eval_stack pointer */
  105.   CELL *fp ;            /* frame ptr into eval_stack for
  106.                            user defined functions */
  107.   /* some useful temporaries */
  108.   CELL *cp , tc ;
  109.   int t ;
  110.  
  111. #ifdef  DEBUG
  112.   CELL *entry_sp = sp ;
  113. #endif
  114.  
  115.   while ( 1 )
  116.     switch( cdp++ -> op )
  117.     {   case  _HALT :
  118.         case  _STOP :  
  119.  
  120. #ifdef   DEBUG
  121. /* check the stack is sane */
  122.                 if ( sp != entry_sp ) bozo("stop") ;
  123.                 return cdp - 1 ;
  124.  
  125.         case  _STOP0  : /* if debugging stops range patterns */
  126.                 if ( sp != entry_sp+1 ) bozo("stop0") ;
  127. #else
  128.         case  _STOP0  :
  129. #endif
  130.                 return cdp -  1 ;
  131.  
  132.         case  _PUSHC :  
  133.             inc_sp() ;
  134.             (void) cellcpy(sp, cdp++ -> ptr) ;
  135.             break ;
  136.  
  137.         case  F_PUSHA :
  138.             if ( (CELL*)cdp->ptr != field && nf < 0 ) split_field0() ;
  139.             /* fall thru */
  140.  
  141.         case  _PUSHA :
  142.         case  A_PUSHA :
  143.             inc_sp() ;
  144.             sp -> ptr = cdp++ -> ptr ;
  145.             break ;
  146.  
  147.         case _PUSHI :  /* put contents of next address on stack*/
  148.             inc_sp() ;
  149.             (void) cellcpy(sp, cdp++ -> ptr) ;
  150.             break ;
  151.             
  152.         case L_PUSHI :  
  153.             /* put the contents of a local var on stack,
  154.                cdp->op holds the offset from the frame pointer */
  155.             inc_sp() ;
  156.             (void) cellcpy(sp, fp + cdp++->op) ;
  157.             break ;
  158.  
  159.         case L_PUSHA : /* put a local address on eval stack */
  160.             inc_sp() ;
  161.             sp->ptr = (PTR)(fp + cdp++->op) ;
  162.             break ;
  163.  
  164.  
  165.         case F_PUSHI :
  166.  
  167.         /* note $0 , RS , FS and OFMT are loaded by _PUSHI */
  168.  
  169.             inc_sp() ;
  170.             if ( nf < 0 )  split_field0() ;
  171.             if ( (t = (CELL *) cdp->ptr - field) <= nf ||
  172.                   t == NF  )
  173.             { (void) cellcpy(sp, cdp++ -> ptr) ; }
  174.             else  /* an unset field */
  175.             { sp->type = C_STRING ;
  176.               sp->ptr = (PTR) & null_str ;
  177.               null_str.ref_cnt++ ;
  178.               cdp++ ;
  179.             }
  180.             break ;
  181.  
  182.         case  FE_PUSHA :
  183.             if ( sp->type != C_DOUBLE )  cast1_to_d(sp) ;
  184.             if ( (t = (int) sp->dval) < 0 )
  185.                 rt_error( "negative field index(%d)", t) ;
  186.             if ( t > MAX_FIELD )
  187.                 rt_overflow("MAX_FIELD", MAX_FIELD) ;
  188.             if ( t && nf < 0 )  split_field0() ;
  189.             sp->ptr = (PTR) &field[t] ;
  190.             break ;
  191.  
  192.         case  FE_PUSHI :
  193.             if ( sp->type != C_DOUBLE )  cast1_to_d(sp) ;
  194.  
  195.             if ( (t = (int) sp->dval) == 0 )
  196.             { (void) cellcpy(sp, &field[0]) ; break ; }
  197.  
  198.             if ( t < 0 )
  199.                   rt_error( "negative field index(%d)", t) ;
  200.             if ( t > MAX_FIELD )
  201.                   rt_overflow("MAX_FIELD", MAX_FIELD) ;
  202.  
  203.             if ( nf < 0)  split_field0() ;
  204.             if ( t <= nf ) (void) cellcpy(sp, &field[t]) ;
  205.             else
  206.             { sp->type = C_STRING ;
  207.               sp->ptr = (PTR) & null_str ;
  208.               null_str.ref_cnt++ ;
  209.             }
  210.             break ; 
  211.  
  212.  
  213.         case  AE_PUSHA :
  214.         /* top of stack has an expr, cdp->ptr points at an
  215.            array, replace the expr with the cell address inside
  216.            the array */
  217.  
  218.             cp = array_find((ARRAY)cdp++->ptr, sp, CREATE) ;
  219.             cell_destroy(sp) ;
  220.             sp->ptr = (PTR) cp ;
  221.             break ;
  222.  
  223.         case  AE_PUSHI :
  224.         /* top of stack has an expr, cdp->ptr points at an
  225.            array, replace the expr with the contents of the
  226.            cell inside the array */
  227.  
  228.             cp = array_find((ARRAY) cdp++->ptr, sp, CREATE) ;
  229.             cell_destroy(sp) ;
  230.             (void) cellcpy(sp, cp) ;
  231.             break ;
  232.  
  233.         case  LAE_PUSHI :
  234.         /*  sp[0] is an expression
  235.             cdp->op is offset from frame pointer of a CELL which
  236.                has an ARRAY in the ptr field, replace expr
  237.             with  array[expr]
  238.         */
  239.             cp = array_find( (ARRAY)fp[cdp++->op].ptr, sp, CREATE) ;
  240.             cell_destroy(sp) ;
  241.             (void) cellcpy(sp, cp) ;
  242.             break ;
  243.             
  244.         case  LAE_PUSHA :
  245.         /*  sp[0] is an expression
  246.             cdp->op is offset from frame pointer of a CELL which
  247.                has an ARRAY in the ptr field, replace expr
  248.             with  & array[expr]
  249.         */
  250.             cp = array_find( (ARRAY)fp[cdp++->op].ptr, sp, CREATE) ;
  251.             cell_destroy(sp) ;
  252.             sp->ptr = (PTR) cp ;
  253.             break ;
  254.             
  255.         case  LA_PUSHA  :
  256.         /*  cdp->op is offset from frame pointer of a CELL which
  257.                has an ARRAY in the ptr field. Push this ARRAY
  258.                on the eval stack
  259.         */
  260.             inc_sp() ;
  261.             sp->ptr = fp[cdp++->op].ptr ;
  262.             break ;
  263.  
  264.         case  A_LOOP :
  265.             cdp = array_loop(cdp,sp,fp) ;
  266.             if ( returning ) return cdp ; /*value doesn't matter*/
  267.             sp -= 2 ;
  268.             break ;
  269.  
  270.         case  _POP : 
  271.             cell_destroy(sp) ;
  272.             sp-- ;
  273.             break ;
  274.  
  275.         case _DUP  :
  276.             (void) cellcpy(sp+1, sp) ;
  277.             sp++ ; break ;
  278.  
  279.         case  _ASSIGN :
  280.             /* top of stack has an expr, next down is an
  281.                address, put the expression in *address and
  282.                replace the address with the expression */
  283.  
  284.             /* don't propagate type C_MBSTRN */
  285.             if ( sp->type == C_MBSTRN ) check_strnum(sp) ;
  286.             sp-- ;
  287.             cell_destroy( ((CELL *)sp->ptr) ) ;
  288.             (void) cellcpy( sp, cellcpy(sp->ptr, sp+1) ) ;
  289.             cell_destroy(sp+1) ;
  290.             break ;
  291.  
  292.         case  F_ASSIGN : /* assign to a field  */
  293.             if (sp->type == C_MBSTRN) check_strnum(sp) ;
  294.             sp-- ;
  295.             field_assign((CELL*)sp->ptr - field, sp+1) ;
  296.             cell_destroy(sp+1) ;
  297.             (void) cellcpy(sp, (CELL *) sp->ptr) ;
  298.             break ;
  299.  
  300.         case  _ADD_ASG:
  301.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  302.             cp = (CELL *) (sp-1)->ptr ;
  303.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  304.  
  305. #if SW_FP_CHECK   /* specific to V7 and XNX23A */
  306.             clrerr();
  307. #endif
  308.             cp->dval += sp-- -> dval ;
  309. #if SW_FP_CHECK
  310.             fpcheck();
  311. #endif
  312.             sp->type = C_DOUBLE ;
  313.             sp->dval = cp->dval ;
  314.             break ;
  315.  
  316.         case  _SUB_ASG:
  317.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  318.             cp = (CELL *) (sp-1)->ptr ;
  319.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  320. #if SW_FP_CHECK
  321.             clrerr();
  322. #endif
  323.             cp->dval -= sp-- -> dval ;
  324. #if SW_FP_CHECK
  325.             fpcheck();
  326. #endif
  327.             sp->type = C_DOUBLE ;
  328.             sp->dval = cp->dval ;
  329.             break ;
  330.  
  331.         case  _MUL_ASG:
  332.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  333.             cp = (CELL *) (sp-1)->ptr ;
  334.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  335. #if SW_FP_CHECK
  336.             clrerr();
  337. #endif
  338.             cp->dval *= sp-- -> dval ;
  339. #if SW_FP_CHECK
  340.             fpcheck();
  341. #endif
  342.             sp->type = C_DOUBLE ;
  343.             sp->dval = cp->dval ;
  344.             break ;
  345.  
  346.         case  _DIV_ASG:
  347.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  348.             cp = (CELL *) (sp-1)->ptr ;
  349.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  350.  
  351. #if  NOINFO_SIGFPE
  352.     CHECK_DIVZERO(sp->dval) ;
  353. #endif
  354.  
  355. #if SW_FP_CHECK
  356.             clrerr();
  357. #endif
  358.             cp->dval /= sp-- -> dval ;
  359. #if SW_FP_CHECK
  360.             fpcheck();
  361. #endif
  362.             sp->type = C_DOUBLE ;
  363.             sp->dval = cp->dval ;
  364.             break ;
  365.  
  366.         case  _MOD_ASG:
  367.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  368.             cp = (CELL *) (sp-1)->ptr ;
  369.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  370.  
  371. #if  NOINFO_SIGFPE
  372.     CHECK_DIVZERO(sp->dval) ;
  373. #endif
  374.  
  375.             cp->dval = fmod(cp->dval,sp-- -> dval) ;
  376.             sp->type = C_DOUBLE ;
  377.             sp->dval = cp->dval ;
  378.             break ;
  379.  
  380.         case  _POW_ASG:
  381.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  382.             cp = (CELL *) (sp-1)->ptr ;
  383.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  384.             cp->dval = pow(cp->dval,sp-- -> dval) ;
  385.             sp->type = C_DOUBLE ;
  386.             sp->dval = cp->dval ;
  387.             break ;
  388.  
  389.         /* will anyone ever use these ? */
  390.  
  391.         case F_ADD_ASG :
  392.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  393.             cp = (CELL *) (sp-1)->ptr ;
  394.             cast1_to_d( cellcpy(&tc, cp) ) ;
  395. #if SW_FP_CHECK
  396.             clrerr();
  397. #endif
  398.             tc.dval += sp-- -> dval ;
  399. #if SW_FP_CHECK
  400.             fpcheck();
  401. #endif
  402.             sp->type = C_DOUBLE ;
  403.             sp->dval = tc.dval ;
  404.             field_assign(cp-field, &tc) ;
  405.             break ;
  406.  
  407.         case F_SUB_ASG :
  408.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  409.             cp = (CELL *) (sp-1)->ptr ;
  410.             cast1_to_d( cellcpy(&tc, cp) ) ;
  411. #if SW_FP_CHECK
  412.             clrerr();
  413. #endif
  414.             tc.dval -= sp-- -> dval ;
  415. #if SW_FP_CHECK
  416.             fpcheck();
  417. #endif
  418.             sp->type = C_DOUBLE ;
  419.             sp->dval = tc.dval ;
  420.             field_assign(cp-field, &tc) ;
  421.             break ;
  422.  
  423.         case F_MUL_ASG :
  424.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  425.             cp = (CELL *) (sp-1)->ptr ;
  426.             cast1_to_d( cellcpy(&tc, cp) ) ;
  427. #if SW_FP_CHECK
  428.             clrerr();
  429. #endif
  430.             tc.dval *= sp-- -> dval ;
  431. #if SW_FP_CHECK
  432.             fpcheck();
  433. #endif
  434.             sp->type = C_DOUBLE ;
  435.             sp->dval = tc.dval ;
  436.             field_assign(cp-field, &tc) ;
  437.             break ;
  438.  
  439.         case F_DIV_ASG :
  440.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  441.             cp = (CELL *) (sp-1)->ptr ;
  442.             cast1_to_d( cellcpy(&tc, cp) ) ;
  443.  
  444. #if  NOINFO_SIGFPE
  445.     CHECK_DIVZERO(sp->dval) ;
  446. #endif
  447.  
  448. #if SW_FP_CHECK
  449.             clrerr();
  450. #endif
  451.             tc.dval /= sp-- -> dval ;
  452. #if SW_FP_CHECK
  453.             fpcheck();
  454. #endif
  455.             sp->type = C_DOUBLE ;
  456.             sp->dval = tc.dval ;
  457.             field_assign(cp-field, &tc) ;
  458.             break ;
  459.  
  460.         case F_MOD_ASG :
  461.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  462.             cp = (CELL *) (sp-1)->ptr ;
  463.             cast1_to_d( cellcpy(&tc, cp) ) ;
  464.  
  465. #if  NOINFO_SIGFPE
  466.     CHECK_DIVZERO(sp->dval) ;
  467. #endif
  468.  
  469.             tc.dval = fmod(tc.dval, sp-- -> dval) ;
  470.             sp->type = C_DOUBLE ;
  471.             sp->dval = tc.dval ;
  472.             field_assign(cp-field, &tc) ;
  473.             break ;
  474.  
  475.         case F_POW_ASG :
  476.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  477.             cp = (CELL *) (sp-1)->ptr ;
  478.             cast1_to_d( cellcpy(&tc, cp) ) ;
  479.             tc.dval = pow(tc.dval, sp-- -> dval) ;
  480.             sp->type = C_DOUBLE ;
  481.             sp->dval = tc.dval ;
  482.             field_assign(cp-field, &tc) ;
  483.             break ;
  484.  
  485.         case _ADD :
  486.             sp-- ;
  487.             if ( TEST2(sp) != TWO_DOUBLES )
  488.                     cast2_to_d(sp) ;
  489. #if SW_FP_CHECK
  490.             clrerr();
  491. #endif
  492.             sp[0].dval += sp[1].dval ;
  493. #if SW_FP_CHECK
  494.             fpcheck();
  495. #endif
  496.             break ;
  497.  
  498.         case _SUB :
  499.             sp-- ;
  500.             if ( TEST2(sp) != TWO_DOUBLES )
  501.                     cast2_to_d(sp) ;
  502. #if SW_FP_CHECK
  503.             clrerr();
  504. #endif
  505.             sp[0].dval -= sp[1].dval ;
  506. #if SW_FP_CHECK
  507.             fpcheck();
  508. #endif
  509.             break ;
  510.  
  511.         case _MUL :
  512.             sp-- ;
  513.             if ( TEST2(sp) != TWO_DOUBLES )
  514.                     cast2_to_d(sp) ;
  515. #if SW_FP_CHECK
  516.             clrerr();
  517. #endif
  518.             sp[0].dval *= sp[1].dval ;
  519. #if SW_FP_CHECK
  520.             fpcheck();
  521. #endif
  522.             break ;
  523.  
  524.         case _DIV :
  525.             sp-- ;
  526.             if ( TEST2(sp) != TWO_DOUBLES )
  527.                     cast2_to_d(sp) ;
  528.  
  529. #if  NOINFO_SIGFPE
  530.     CHECK_DIVZERO(sp[1].dval) ;
  531. #endif
  532.  
  533. #if SW_FP_CHECK
  534.             clrerr();
  535. #endif
  536.             sp[0].dval /= sp[1].dval ;
  537. #if SW_FP_CHECK
  538.             fpcheck();
  539. #endif
  540.             break ;
  541.  
  542.         case _MOD :
  543.             sp-- ;
  544.             if ( TEST2(sp) != TWO_DOUBLES )
  545.                     cast2_to_d(sp) ;
  546.  
  547. #if  NOINFO_SIGFPE
  548.     CHECK_DIVZERO(sp[1].dval) ;
  549. #endif
  550.  
  551.             sp[0].dval = fmod(sp[0].dval,sp[1].dval) ;
  552.             break ;
  553.  
  554.         case _POW :
  555.             sp-- ;
  556.             if ( TEST2(sp) != TWO_DOUBLES )
  557.                     cast2_to_d(sp) ;
  558.             sp[0].dval = pow(sp[0].dval,sp[1].dval) ;
  559.             break ;
  560.  
  561.         case _NOT :
  562.         reswitch_1:
  563.             switch( sp->type )
  564.             { case C_NOINIT :
  565.                     sp->dval = 1.0 ; break ;
  566.               case C_DOUBLE :
  567.                     sp->dval = D2BOOL(sp->dval) ? 0.0 : 1.0 ;
  568.                     break ;
  569.               case C_STRING :
  570.                     sp->dval = string(sp)->len ? 0.0 : 1.0 ;
  571.                     free_STRING(string(sp)) ;
  572.                     break ;
  573.               case C_STRNUM : /* test as a number */
  574.                     sp->dval = D2BOOL(sp->dval) ? 0.0 : 1.0 ;
  575.                     free_STRING(string(sp)) ;
  576.                     break ;
  577.               case C_MBSTRN :
  578.                     check_strnum(sp) ;
  579.                     goto reswitch_1 ;
  580.               default :
  581.                     bozo("bad type on eval stack") ;
  582.             }
  583.             sp->type = C_DOUBLE ;
  584.             break  ;
  585.  
  586.         case _TEST :
  587.         reswitch_2:
  588.             switch( sp->type )
  589.             { case C_NOINIT :
  590.                     sp->dval = 0.0 ; break ;
  591.               case C_DOUBLE :
  592.                     sp->dval = D2BOOL(sp->dval) ? 1.0 : 0.0 ;
  593.                     break ;
  594.               case C_STRING :
  595.                     sp->dval  = string(sp)->len ? 1.0 : 0.0 ;
  596.                     free_STRING(string(sp)) ;
  597.                     break ;
  598.               case C_STRNUM : /* test as a number */
  599.                     sp->dval = D2BOOL(sp->dval) ? 1.0 : 0.0 ;
  600.                     free_STRING(string(sp)) ;
  601.                     break ;
  602.               case C_MBSTRN :
  603.                     check_strnum(sp) ;
  604.                     goto reswitch_2 ;
  605.               default :
  606.                     bozo("bad type on eval stack") ;
  607.             }
  608.             sp->type = C_DOUBLE ;
  609.             break ;
  610.  
  611.         case _UMINUS :
  612.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  613.             sp->dval = - sp->dval ;
  614.             break ;
  615.  
  616.         case _UPLUS :  
  617.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  618.             break ;
  619.  
  620.         case _CAT :
  621.             { unsigned len1, len2 ;
  622.               char *str1, *str2 ;
  623.               STRING *b ;
  624.               
  625.               sp-- ;
  626.               if ( TEST2(sp) != TWO_STRINGS )
  627.                     cast2_to_s(sp) ;
  628.               str1 = string(sp)->str ;
  629.               len1 = string(sp)->len ;
  630.               str2 = string(sp+1)->str ;
  631.               len2 = string(sp+1)->len ;
  632.  
  633.               b = new_STRING((char *)0, len1+len2) ;
  634.               (void) memcpy(b->str, str1, SIZE_T(len1)) ;
  635.               (void) memcpy(b->str + len1, str2, SIZE_T(len2)) ;
  636.               free_STRING(string(sp)) ;
  637.               free_STRING( string(sp+1) ) ;
  638.  
  639.               sp->ptr = (PTR) b ;
  640.               break ;
  641.             }
  642.  
  643.         case _PUSHINT :
  644.             inc_sp() ;
  645.             sp->type = cdp++ -> op ;
  646.             break ;
  647.  
  648.         case _BUILTIN :
  649.         case _PRINT :
  650.             sp = (* (PF_CP) cdp++ -> ptr) (sp) ;
  651.             break ;
  652.  
  653.         case _POST_INC :
  654.             (void) cellcpy(sp, cp = (CELL *)sp->ptr) ;
  655.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  656.             cp->dval += 1.0 ;
  657.             break ;
  658.  
  659.         case _POST_DEC :
  660.             (void) cellcpy(sp, cp = (CELL *)sp->ptr) ;
  661.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  662.             cp->dval -= 1.0 ;
  663.             break ;
  664.  
  665.         case _PRE_INC :
  666.             cp = (CELL *) sp->ptr ;
  667.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  668.             sp->dval = cp->dval += 1.0 ;
  669.             sp->type = C_DOUBLE ;
  670.             break ;
  671.  
  672.         case _PRE_DEC :
  673.             cp = (CELL *) sp->ptr ;
  674.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  675.             sp->dval = cp->dval -= 1.0 ;
  676.             sp->type = C_DOUBLE ;
  677.             break ;
  678.  
  679.  
  680.         case F_POST_INC  :
  681.             cp = (CELL *) sp->ptr ;
  682.             (void) cellcpy(sp, cellcpy(&tc, cp) ) ;
  683.             cast1_to_d(&tc) ;
  684.             tc.dval += 1.0 ;
  685.             field_assign(cp-field, &tc) ;
  686.             break ;
  687.  
  688.         case F_POST_DEC  :
  689.             cp = (CELL *) sp->ptr ;
  690.             (void) cellcpy(sp, cellcpy(&tc, cp) ) ;
  691.             cast1_to_d(&tc) ;
  692.             tc.dval -= 1.0 ;
  693.             field_assign(cp-field, &tc) ;
  694.             break ;
  695.  
  696.         case F_PRE_INC :
  697.             cp = (CELL *) sp->ptr ;
  698.             cast1_to_d(cellcpy(&tc, cp)) ;
  699.             sp->dval = tc.dval += 1.0 ;
  700.             sp->type = C_DOUBLE ;
  701.             field_assign(cp-field, sp) ;
  702.             break ;
  703.  
  704.         case F_PRE_DEC :
  705.             cp = (CELL *) sp->ptr ;
  706.             cast1_to_d(cellcpy(&tc, cp)) ;
  707.             sp->dval = tc.dval -= 1.0 ;
  708.             sp->type = C_DOUBLE ;
  709.             field_assign(cp-field, sp) ;
  710.             break ;
  711.  
  712.         case _JMP  :
  713.             cdp += cdp->op - 1 ;
  714.             break ;
  715.  
  716.         case _JNZ  :
  717.             /* jmp if top of stack is non-zero and pop stack */
  718.             if ( test( sp ) )
  719.                 cdp += cdp->op - 1 ;
  720.             else  cdp++ ;
  721.             cell_destroy(sp) ;
  722.             sp-- ;
  723.             break ;
  724.  
  725.         case _JZ  :
  726.             /* jmp if top of stack is zero and pop stack */
  727.             if ( ! test( sp ) )
  728.                 cdp += cdp->op - 1 ;
  729.             else  cdp++ ;
  730.             cell_destroy(sp) ;
  731.             sp-- ;
  732.             break ;
  733.  
  734.     /*  the relation operations */
  735.     /*  compare() makes sure string ref counts are OK */
  736.         case  _EQ :
  737.             t = compare(--sp) ;
  738.             sp->type = C_DOUBLE ;
  739.             sp->dval = t == 0 ? 1.0 : 0.0 ;
  740.             break ;
  741.  
  742.         case  _NEQ :
  743.             t = compare(--sp) ;
  744.             sp->type = C_DOUBLE ;
  745.             sp->dval = t ? 1.0 : 0.0 ;
  746.             break ;
  747.  
  748.         case  _LT :
  749.             t = compare(--sp) ;
  750.             sp->type = C_DOUBLE ;
  751.             sp->dval = t < 0 ? 1.0 : 0.0 ;
  752.             break ;
  753.  
  754.         case  _LTE :
  755.             t = compare(--sp) ;
  756.             sp->type = C_DOUBLE ;
  757.             sp->dval = t <= 0 ? 1.0 : 0.0 ;
  758.             break ;
  759.  
  760.         case  _GT :
  761.             t = compare(--sp) ;
  762.             sp->type = C_DOUBLE ;
  763.             sp->dval = t > 0 ? 1.0 : 0.0 ;
  764.             break ;
  765.  
  766.         case  _GTE :
  767.             t = compare(--sp) ;
  768.             sp->type = C_DOUBLE ;
  769.             sp->dval = t >= 0 ? 1.0 : 0.0 ;
  770.             break ;
  771.  
  772.         case  _MATCH :
  773.             /* does sp[-1] match sp[0] as re */
  774.             if ( sp->type != C_RE )  cast_to_RE(sp) ;
  775.  
  776.             if ( (--sp)->type < C_STRING )  cast1_to_s(sp) ;
  777.             t = REtest(string(sp)->str, (sp+1)->ptr) ; 
  778.  
  779.             free_STRING(string(sp)) ;
  780.             sp->type = C_DOUBLE ;
  781.             sp->dval = t ? 1.0 : 0.0 ;
  782.             break ;
  783.  
  784.         case  A_TEST :
  785.         /* entry :  sp[0].ptr-> an array
  786.                     sp[-1]  is an expression
  787.  
  788.            we compute   expression in array  */
  789.             sp-- ;
  790.             cp = array_find( (sp+1)->ptr, sp, NO_CREATE) ;
  791.             cell_destroy(sp) ;
  792.             sp->type = C_DOUBLE ;
  793.             sp->dval = (cp!=(CELL*)0)  ? 1.0 : 0.0 ;
  794.             break ;
  795.  
  796.         case  A_DEL :
  797.         /* sp[0].ptr ->  array)
  798.            sp[-1] is an expr
  799.            delete  array[expr]  */
  800.  
  801.             array_delete(sp->ptr, sp-1) ;
  802.             cell_destroy(sp-1) ;
  803.             sp -= 2 ;
  804.             break ;
  805.         
  806.         /* form a multiple array index */
  807.         case A_CAT :
  808.             sp = array_cat(sp, cdp++->op) ;
  809.             break ;
  810.  
  811.         case  _EXIT0 :
  812.             longjmp( exit_jump, 1) ;
  813.  
  814.         case  _EXIT  :
  815.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  816.             exit_code = (int) sp->dval ;
  817.             longjmp( exit_jump, 1) ;
  818.  
  819.         case  _NEXT :
  820.             longjmp(next_jump, 1) ;
  821.  
  822.         case  _RANGE :
  823. /* test a range pattern:  pat1, pat2 { action }
  824.    entry :
  825.        cdp[0].op -- a flag, test pat1 if on else pat2
  826.        cdp[1].op -- offset of pat2 code from cdp
  827.        cdp[2].op -- offset of action code from cdp
  828.        cdp[3].op -- offset of code after the action from cdp
  829.        cdp[4] -- start of pat1 code
  830. */
  831.  
  832. #define FLAG    cdp[0].op
  833. #define PAT2    cdp[1].op
  834. #define ACTION    cdp[2].op
  835. #define FOLLOW    cdp[3].op
  836. #define PAT1      4
  837.  
  838.             if ( FLAG )  /* test again pat1 */
  839.             { 
  840.               (void) execute(cdp + PAT1,sp, fp) ;
  841.               t = test(sp+1) ;
  842.               cell_destroy(sp+1) ;
  843.               if ( t )  FLAG = 0 ;
  844.               else
  845.               { cdp += FOLLOW ;
  846.                 break ;  /* break the switch */
  847.               }
  848.             }
  849.  
  850.             /* test against pat2 and then perform the action */
  851.             (void) execute(cdp + PAT2, sp, fp) ;
  852.             FLAG  = test(sp+1) ;
  853.             cell_destroy(sp+1) ; 
  854.             cdp += ACTION ;
  855.             break ;
  856.  
  857. /* function calls  */
  858.  
  859.       case  _RET0  :
  860.             inc_sp() ;
  861.             sp->type = C_NOINIT ;
  862.             /* fall thru */
  863.  
  864.       case  _RET   :
  865.  
  866. #ifdef  DEBUG
  867.             if ( sp != entry_sp+1 ) bozo("ret") ;
  868. #endif
  869.             returning = 1 ;
  870.             return  cdp-1 ;
  871.  
  872.       case  _CALL  :
  873.  
  874.             { FBLOCK *fbp = (FBLOCK*) cdp++->ptr ;
  875.               int a_args = cdp++->op ; /* actual number of args */
  876.               CELL *nfp = sp - a_args + 1 ; /* new fp for callee */
  877.               CELL *local_p = sp+1; /* first local argument on stack */
  878.               char *type_p ;  /* pts to type of an argument */
  879.  
  880.               if ( fbp->nargs ) type_p = fbp->typev + a_args ;
  881.  
  882.               /* create space for locals */
  883.               if ( t = fbp->nargs - a_args ) /* have local args */
  884.               {
  885.                 if ( sp + t >= eval_stack + EVAL_STACK_SIZE - SAFETY )
  886.                    eval_overflow() ;
  887.  
  888.                 while ( t-- )  
  889.                 { (++sp)->type = C_NOINIT ;
  890.                   if ( *type_p++ == ST_LOCAL_ARRAY )
  891.                         sp->ptr = (PTR) new_ARRAY() ;
  892.                 }
  893.               }
  894.               type_p-- ; /* *type_p is type of last arg */ 
  895.  
  896.               (void) execute(fbp->code, sp, nfp) ;
  897. #ifdef  DEBUG
  898. if ( !returning )  bozo("call") ;
  899. #endif
  900.               returning = 0 ;
  901.  
  902.               /* cleanup the callee's arguments */
  903.               if ( sp >= nfp ) 
  904.               {
  905.                 cp = sp+1 ;  /* cp -> the function return */
  906.  
  907.                 do
  908.                 {
  909.                   if ( *type_p-- == ST_LOCAL_ARRAY )
  910.                   {  if ( sp >= local_p ) array_free(sp->ptr) ; }
  911.                   else  cell_destroy(sp) ;
  912.  
  913.                 } while ( --sp >= nfp ) ;
  914.                     
  915.                 (void) cellcpy(++sp, cp) ;
  916.                 cell_destroy(cp) ;
  917.               }
  918.               else  sp++ ; /* no arguments passed */
  919.             }
  920.             break ;
  921.  
  922.         default :
  923.             bozo("bad opcode") ;
  924.     }
  925. }
  926.  
  927. int test( cp )  /* test if a cell is null or not */
  928.   register CELL *cp ;
  929. reswitch :
  930.  
  931.   switch ( cp->type )
  932.   {
  933.     case C_NOINIT :  return  0 ;
  934.     case C_STRNUM :  /* test as a number */
  935.     case C_DOUBLE :  return  cp->dval != 0.0 ;
  936.     case C_STRING :  return  string(cp)->len ;
  937.     case C_MBSTRN :  check_strnum(cp) ; goto reswitch ;
  938.  
  939.     default :
  940.       bozo("bad cell type in call to test") ;
  941.   }
  942. }
  943.  
  944. /* compare cells at cp and cp+1 and
  945.    frees STRINGs at those cells
  946. */
  947.  
  948. static int compare(cp)
  949.   register CELL *cp ;
  950. { int k ;
  951.  
  952. reswitch :
  953.  
  954.   switch( TEST2(cp) )
  955.   { case TWO_NOINITS :  return 0 ; 
  956.     
  957.     case TWO_DOUBLES :
  958.     two_d:
  959.             return  cp->dval > (cp+1)->dval ? 1 :
  960.                     cp->dval < (cp+1)->dval ? -1 : 0 ;
  961.     
  962.     case TWO_STRINGS :
  963.     case STRING_AND_STRNUM :
  964.     two_s:
  965.             k = strcmp(string(cp)->str, string(cp+1)->str) ;
  966.             free_STRING( string(cp) ) ;
  967.             free_STRING( string(cp+1) ) ;
  968.             return k ;
  969.  
  970.     case  NOINIT_AND_DOUBLE  :
  971.     case  NOINIT_AND_STRNUM  :
  972.     case  DOUBLE_AND_STRNUM  :
  973.     case TWO_STRNUMS :
  974.             cast2_to_d(cp) ; goto two_d ;
  975.  
  976.     case  NOINIT_AND_STRING  :
  977.     case  DOUBLE_AND_STRING  :
  978.             cast2_to_s(cp) ; goto two_s ;
  979.  
  980.     case  TWO_MBSTRNS :
  981.             check_strnum(cp) ; check_strnum(cp+1) ;
  982.             goto reswitch ;
  983.  
  984.     case  NOINIT_AND_MBSTRN :
  985.     case  DOUBLE_AND_MBSTRN :
  986.     case  STRING_AND_MBSTRN :
  987.     case  STRNUM_AND_MBSTRN :
  988.             check_strnum( cp->type == C_MBSTRN ? cp : cp+1 ) ;
  989.             goto reswitch ;
  990.  
  991.     default :  /* there are no default cases */
  992.             bozo("bad cell type passed to compare") ;
  993.   }
  994. }
  995.  
  996. /* does not assume target was a cell, if so
  997.    then caller should have made a previous
  998.    call to cell_destroy  */
  999.  
  1000. CELL *cellcpy(target, source)
  1001.   register CELL *target, *source ;
  1002. { switch( target->type = source->type )
  1003.   { case C_NOINIT : 
  1004.     case C_SPACE  : 
  1005.     case C_SNULL  :
  1006.             break ;
  1007.  
  1008.     case C_DOUBLE :
  1009.             target->dval = source->dval ;
  1010.             break ;
  1011.  
  1012.     case C_STRNUM :
  1013.             target->dval = source->dval ;
  1014.             /* fall thru */
  1015.  
  1016.     case C_REPL    :
  1017.     case C_MBSTRN  :
  1018.     case C_STRING  :
  1019.             string(source)->ref_cnt++ ;
  1020.             /* fall thru */
  1021.  
  1022.     case C_RE  :
  1023.             target->ptr = source->ptr ;
  1024.             break ;
  1025.  
  1026.     case  C_REPLV :
  1027.             (void)  replv_cpy(target, source) ;
  1028.             break ;
  1029.  
  1030.     default :
  1031.             bozo("bad cell passed to cellcpy()") ;
  1032.             break ;
  1033.   }
  1034.   return  target ;
  1035. }
  1036.  
  1037. #ifdef   DEBUG
  1038.  
  1039. void  DB_cell_destroy(cp)    /* HANGOVER time */
  1040.   register CELL *cp ;
  1041. {
  1042.   switch( cp->type )
  1043.   { case C_NOINIT :
  1044.     case C_DOUBLE :  break ;
  1045.  
  1046.     case C_MBSTRN :
  1047.     case C_STRING :
  1048.     case C_STRNUM :
  1049.             if ( -- string(cp)->ref_cnt == 0 )
  1050.                 zfree(string(cp) , string(cp)->len+5) ;
  1051.             break ;
  1052.  
  1053.     case  C_RE :
  1054.             bozo("cell destroy called on RE cell") ;
  1055.     default :
  1056.             bozo("cell destroy called on bad cell type") ;
  1057.   }
  1058. }
  1059.  
  1060. #endif
  1061.